package org.paybiz.core.payplatform.bill99.service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.paybiz.constant.PayConstant;
import org.paybiz.core.payplatform.bill99.constant.Bill99Constant;
import org.paybiz.core.payplatform.bill99.util.Pkipair;
import org.paybiz.core.service.pay.PayService;
import org.paybiz.model.PayModel;
import org.paybiz.model.PayReqResultDO;
import org.paybiz.util.DateUtil;
import org.paybiz.util.DynamicConfig;
import org.paybiz.util.PaySignUtil;
import org.springframework.stereotype.Service;

/**
 * 快钱支付
 * 
 * @author nassir wen
 * @data 2012-5-12 下午05:41:15
 * @version V2.5
 * @Company: MSD.
 * @Copyright Copyright (c) 2012
 */
@Service("bill99Service")
public class Bill99ServiceImpl implements PayService {
    private final static Log logger = LogFactory
            .getLog(Bill99ServiceImpl.class);

    // 内部密钥
    private static String msdValue = "";

    // 商户编号
    private static String bill99_MerId = "";

    // 支付回调链接
    private static String bill99_returnUrl = "";

    // 支付链接
    private static String bill99_payUrl = "";
    
    //支付异步回调链接
    private static String bill99_notifyUrl = "";

    // 编码方式，1代表 UTF-8; 2 代表 GBK; 3代表 GB2312 默认为1,该参数必填。
    private static String inputCharset = "1";

    // 网关版本，固定值：v2.0,该参数必填。
    private static String version = "v2.0";

    // 语言种类，1代表中文显示，2代表英文显示。默认为1,该参数必填。
    private static String language = "1";

    // 签名类型,该值为4，代表PKI加密方式,该参数必填。
    private static String signType = "4";

    private static String charset = "UTF-8";

    static {
        bill99_MerId = DynamicConfig.getInstance().getValue(Bill99Constant.BILL99_MERID);
        msdValue = DynamicConfig.getInstance().getValue(PayConstant.PAY_BIZ_KEY);
        bill99_returnUrl = DynamicConfig.getInstance().getValue(
                Bill99Constant.BILL99_RETURNURL);
        bill99_notifyUrl = DynamicConfig.getInstance().getValue(
                Bill99Constant.BILL99_NOTIFYURL);
        bill99_payUrl = DynamicConfig.getInstance().getValue(Bill99Constant.BILL99_PAYURL);
    }

    /**
     * 快钱支付
     */
    public PayReqResultDO pay(PayModel payDO) {
        PayReqResultDO payReqResult = new PayReqResultDO();
        Map<String, String> params = createParamsMap(payDO);
        String signMsg = Pkipair.signMsg(Pkipair.getSignMsgVal(params));
        StringBuilder payUrl = new StringBuilder(300);
        payUrl.append(bill99_payUrl).append("?");
        List<String> keys = new ArrayList<String>(params.keySet());
        try {
            for (int i = 0; i < keys.size(); i++) {
                String key = (String) keys.get(i);
                String value = (String) params.get(key);
                payUrl.append(key).append("=")
                        .append(URLEncoder.encode(value, charset) + "&");
            }
            // 签名中包含特殊字符需转义
            signMsg = URLEncoder.encode(signMsg, charset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        payUrl.append("signMsg").append("=").append(signMsg);
        payReqResult.setResult(0);
        payReqResult.setPayUrl(payUrl.toString());
        payReqResult.setHmac(PaySignUtil.getPayReqResultDOHmac(payReqResult,
                msdValue));
        return payReqResult;
    }

    @Override
    public int autoCheckOrder(String orderId, Date date, Integer tag) {
        return 0;
    }

    /**
     * 构造支付参数map
     * 
     * @param pay
     * @return
     */
    private Map<String, String> createParamsMap(PayModel pay) {
        Map<String, String> params = new LinkedHashMap<String, String>();
        params.put("inputCharset", inputCharset);
        // 接收支付结果的页面地址，该参数一般置为空即可。
        params.put("pageUrl",StringUtils.isNotEmpty(pay.getSynCallbackUrl()) ? pay.getSynCallbackUrl() :  bill99_returnUrl);
        // 服务器接收支付结果的后台地址，该参数务必填写，不能为空。
        params.put("bgUrl", StringUtils.isNotEmpty(pay.getAsynCallbackUrl()) ? pay.getAsynCallbackUrl() : bill99_notifyUrl);
        params.put("version", version);
        params.put("language", language);
        params.put("signType", signType);
        params.put("merchantAcctId", bill99_MerId);
        // 支付人姓名,可以为空。
        params.put("payerName", "");
        // 支付人联系类型，1 代表电子邮件方式；2 代表手机联系方式。可以为空。
        params.put("payerContactType", "");
        // 支付人联系方式，与payerContactType设置对应，payerContactType为1，则填写邮箱地址；payerContactType为2，则填写手机号码。可以为空。
        params.put("payerContact", "");
        // 商户订单号，以下采用时间来定义订单号，商户可以根据自己订单号的定义规则来定义该值，不能为空。
        params.put("orderId", pay.getOrderId());
        params.put("orderAmount", pay.getPayMoney() + "");
        params.put("orderTime",
                DateUtil.convertDateToString(new Date(), "yyyyMMddHHmmss"));
        // 商品名称，可以为空。
        params.put("productName", pay.getSubject());
        // 商品数量，可以为空。
        params.put("productNum", "1");
        // 商品代码，可以为空。
        params.put("productId", "");
        // 商品描述，可以为空。
        params.put("productDesc", pay.getBody());
        // 扩展字段1，商户可以传递自己需要的参数，支付完快钱会原值返回，可以为空。
        params.put("ext1", pay.getResultUrl());
        // 扩展自段2，商户可以传递自己需要的参数，支付完快钱会原值返回，可以为空。
        params.put("ext2", "");
        // 支付方式，一般为00，代表所有的支付方式。如果是银行直连商户，该值为10，必填。需开通
        params.put("payType", "00");
        // 银行代码，如果payType为00，该值可以为空；如果payType为10，该值必须填写，具体请参考银行列表。
        params.put("bankId", "");
        // 固定选择值： 1、0 1代表同一订单号只允许提交1次； 0表示同一订单号在没有支付成功的前提下可重复提交多次。 默认为0
        params.put("redoFlag", "0");
        params.put("pid", "");
        return params;
    }
}
